package RSSLite;

use strict;
use Digest::MD5 qw(md5_hex);

our %LinkId;

END {
	eval {
		dbmclose(%LinkId);
	};
}

sub new {
	my $class = shift || die "object needed!!";
	my %param = @_;
	my $self = {
		version	=> $param{'version'},
		encoding => $param{'encoding'},
	};
	
	eval {
		dbmopen(%LinkId,'/tmp/item_link_id',0666);
	};
	
	bless $self, $class;
	return $self;
}

sub channel {
	my $self = shift;
	my %param = @_;
	
	$self->{rss}->{title} = _escape( $param{'title'} );
	$self->{rss}->{link} = _escape ( $param{'link'} );
	$self->{rss}->{description} = _escape( $param{'description'} );
	$self->{rss}->{date} = $param{'date'} || time();
	$self->{rss}->{creator} = $param{'creator'};
		
	return 1;
}

sub add_item {
	my $self = shift;
	my %param = @_;
	my $item;
	
	##$param{'title'} =~ s!<.+?>!!gi;
	$item->{title} = _escape( $param{'title'} );
	$item->{link}  = _escape( $param{'link'} );
	$item->{description} = _escape( $param{'description'} );
	$item->{date} = $param{'date'} || _getLinkTime( $item->{link} );
	$item->{creator} = $param{'creator'};
	$item->{category} = $param{'category'};
	
	push ( @{$self->{rss}->{item}}, $item );
	
	return 1;
}

sub as_string {
	my $self = shift;
	
	if ( $self->{version} eq "1.0" )
	{
		return $self->rss10;
	}
	elsif ( $self->{version} eq "2.0" ) {
		return $self->rss20;
	}
	else
	{
		return $self->rss10;
	}
}

sub save {
	my $self = shift;
	my $filepath = shift;
	
	open FILE, ">$filepath" || die "can't open file";
	print FILE $self->as_string();
	close FILE;
	
	return 1;
}

sub _escape {
	my $str = shift;
	
	##$str =~ s/(([\x80-\xff].)*)[\x80-\xff]?$/$1/; ##한글처리
	$str =~ s!&!&amp;!gi;  # &
	$str =~ s!<!&lt;!gi; # <
	$str =~ s!>!&gt;!gi; # >
	$str =~ s!"!&quot;!gi;  # "
	
	return $str;
}


sub _getLinkTime {
	my $url = shift;
	my ( $md5 ) = md5_hex($url);
	
	unless ( $LinkId{$md5} )
	{
		$LinkId{$md5} = time();
	}
	
	return $LinkId{$md5};
}


sub date_rss10 {
	my $tsec = shift;
	return undef unless ( $tsec );
	
	my ($sec,$min,$hour,$mday,$mon,$year,undef,undef,undef) = localtime($tsec);
	
	return sprintf("%04d-%02d-%02dT%02d:%02d:%02d+09:00", $year+1900, $mon+1, $mday, $hour, $min, $sec);
}
  	
sub rss10 {
	my $self = shift;
	
	my $encoding = $self->{encoding};
	my $c_title = $self->{rss}->{title};
	my $c_link = $self->{rss}->{link};
	my $c_description = $self->{rss}->{description};
	my $c_date = date_rss10 ( $self->{rss}->{date} );
	my $c_creator = $self->{rss}->{creator};
	
	my $output;
	
	$output .= <<"OUTPUT";
<?xml version="1.0" encoding="$encoding"?>

<rdf:RDF
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns="http://purl.org/rss/1.0/"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
 xmlns:admin="http://webns.net/mvcb/"
 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
>
OUTPUT
	
	$output .= <<"OUTPUT";
<channel rdf:about="$c_link">
<title>$c_title</title>
<link>$c_link</link>
<description>$c_description</description>
OUTPUT

	if ( $c_date )
	{
		$output .= sprintf(
			"<dc:date>%s</dc:date>\n",
			$c_date
		);
	}
	
	if ( $c_creator )
	{
		$output .= sprintf(
			"<dc:creator>%s</dc:creator>\n",
			$c_creator
		);
	}
	
	$output .= <<'OUTPUT';
<items>
 <rdf:Seq>
OUTPUT

	foreach my $item ( @{$self->{rss}->{item}} ) {
		my $i_link = $item->{link};
		
		$output .= <<"OUTPUT";
<rdf:li rdf:resource="$i_link" />
OUTPUT
	}
	
	$output .= <<'OUTPUT';
 </rdf:Seq>
</items>
</channel>
OUTPUT
	
	foreach my $item ( @{$self->{rss}->{item}} ) {
		
		my $i_title = $item->{title};
		my $i_link = $item->{link};
		my $i_description = $item->{description};
		my $i_date = date_rss10( $item->{date} );
		my $i_creator = $item->{creator};
		my $i_category = $item->{category};
		
		$output .= <<"OUTPUT";
<item rdf:about="$i_link">
<title>$i_title</title>
<link>$i_link</link>
OUTPUT

		if ( $i_description )
		{
			$output .= sprintf(
				"<description>%s</description>\n",
				$i_description
			);
		}
		
		if ( $i_category )
		{
			$output .= sprintf(
				"<dc:subject>%s</dc:subject>\n",
				$i_category
			);
		}
		
		if ( $i_date )
		{
			$output .= sprintf(
				"<dc:date>%s</dc:date>\n",
				$i_date
			);
		}
		
		if ( $i_creator )
		{
			$output .= sprintf(
				"<dc:creator>%s</dc:creator>\n",
				$i_creator
			);
		}	
		
		$output .= <<'OUTPUT';
</item>
OUTPUT

	}
	
	$output .= <<'OUTPUT';
</rdf:RDF>
OUTPUT
}


sub rss20 {
	my $self = shift;
	
	my $encoding = $self->{encoding};
	my $c_title = $self->{rss}->{title};
	my $c_link = $self->{rss}->{link};
	my $c_description = $self->{rss}->{description};
	my $c_date = date_rss10 ( $self->{rss}->{date} );
	my $c_creator = $self->{rss}->{creator};
	
	my $output;
	
	$output .= <<'OUTPUT';
<?xml version="1.0" encoding="$encoding"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
OUTPUT

	$output .= <<"OUTPUT";
<channel>
<title>$c_title</title>
<link>$c_link</link>
<description>$c_description</description>
OUTPUT

	foreach my $item ( @{$self->{rss}->{item}} ) {
		
		my $i_title = $item->{title};
		my $i_link = $item->{link};
		my $i_description = $item->{description};
		my $i_date = date_rss10( $item->{date} );
		my $i_creator = $item->{creator};
		my $i_category = $item->{category};
		
		$output .= <<"OUTPUT";
<item>
<title>$i_title</title>
<link>$i_link</link>
<guid>$i_link</guid>
OUTPUT

		if ( $i_description )
		{
			$output .= sprintf(
				"<description>%s</description>\n",
				$i_description
			);
		}
		
		if ( $i_date )
		{
			$output .= sprintf(
				"<pubDate>%s</pubDate>\n",
				$i_date
			);
		}
		
		if ( $i_creator )
		{
			$output .= sprintf(
				"<author>%s</author>\n",
				$i_creator
			);
		}	
		
		$output .= <<'OUTPUT';
</item>
OUTPUT

	}
	
	$output .= <<'OUTPUT';
</channel>
</rss>
OUTPUT
}

1;

__END__

=head1 NAME

RSSLite - Easy RSS Maker ( Make Only )

=head1 SYNOPSIS

 use RSSLite;
 my $rss = new RSSLite(version => '1.0', encoding=>"euc-kr");

 $rss->channel(
  title        => "전자신문",
  link         => "http://www.etnews.co.kr",
  description  => "전자신문 - The Electronic Times Internet",
 );

 $rss->add_item(
  title       => "title",
  link        => "http://link",
  description => "",
 );

 print "content-type : text/xml\n\n";
 print $rss->as_string;

=head1 AUTHOR

김기석, kiseok7@gmail.com

=head1 SEE ALSO

L<http://search.cpan.org/dist/XML-RSS/>

=cut

